home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 201-220 / scopedisk211 / climax / climax.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  21.3 KB  |  784 lines

  1. /*************************
  2.  
  3. Have you ever wanted CLI on a custom screen with 25 lines of 80 characters? 
  4. Here it is!  By Paul Kienitz, first version 11/27/88.  When compiling with Aztec
  5. C, DO NOT use the +M (3.6) or -BD (5.0) stack checking option.  There are some
  6. provisions for compiling it without Aztec, but they are UNTESTED AND INCOMPLETE.
  7. Last revision date:  12/1/91.
  8.  
  9. Use the +A flag on the Aztec linker!
  10.  
  11. Improvements needed, maybe:
  12.    o Add full public screen support.
  13.    o Option to select an arbitrary font.
  14.    o Option to set RGB colors?
  15.    o -Mn option to set overscanmargin?
  16.    o hot key to bring to front and activate?  Make your own, I don't need one.
  17.    o Invisible screen gadgets?  Nah, too difficult to make text show through.
  18.  
  19. **************************/
  20.  
  21.  
  22. /* note to myself: GMC shortcoming with ^C interrupt inside Execute(), or with
  23. Run ... If you Run a program in a GMC window that writes to the window, ^C will
  24. not interrupt it, though it does with some (not all) other console handlers.
  25. This means commands run with the DO option cannot be ^C'ed in a GMC window.
  26. Other incompatibilities of GMC 9.6 with the 2.0 CON: handler are: no support for
  27. simple-refresh windows, and hence no support of text-cut-with-mouse, so that the
  28. -S or SMARTREFRESH option must be used; no support for /WINDOW or /SCREEN or /
  29. AUTO or /BORDERLESS or /BACKDROP, etc... also the filename completer only works
  30. in the curent directory, under V36 kickstart.  The E option, to make it use a
  31. different font, also does not work with GMC. */
  32.  
  33. #include <exec/exec.h>
  34. #include <exec/execbase.h>
  35. #include <intuition/intuition.h>
  36. #include <graphics/displayinfo.h>
  37. #include <graphics/gfxbase.h>
  38. #include <workbench/workbench.h>
  39. #include <workbench/startup.h>
  40. #include <libraries/dosextens.h>
  41. #include <string.h>
  42. #include <Paul.h>
  43.  
  44.  
  45. #define SEMNAME "CLImax gate"
  46.  
  47.  
  48. #define BOLD "\2331m"
  49. #define NORMAL "\2330m"
  50.  
  51.  
  52. #define GREENISHNESS    {0x484, 0x000, 0x0b0, 0xcc0}
  53. #define DEFAULTISHNESS    {0x05a, 0xfff, 0x002, 0xf80}
  54.  
  55. #define SCLI struct CommandLineInterface
  56.  
  57.  
  58. #define WDHANDLER "CON"
  59. #define WDLEFT    234
  60. #define WDTOP     123
  61. #define WDWIDTH   345
  62. #define WDHEIGHT  69
  63. #define WDTITLE   "unendurable pleasure indefinitely prolonged"
  64. #define WDCMPLEN  30
  65.  
  66. struct {
  67.     str handler;
  68.     short left, top, width, height;
  69.     str title;
  70.     adr windowptr;
  71. } WFargs = { WDHANDLER, WDLEFT, WDTOP, WDWIDTH, WDHEIGHT, WDTITLE, null };
  72.  
  73. char chand[300];
  74.  
  75.  
  76. typedef struct {
  77.     adr ibase, gbase, dosbase;
  78.     struct TextFont *fawnt;
  79.     struct Screen *scr;
  80.     struct Window *win;
  81.     BPTR wandle, ceedee;
  82.     struct NewWindow *wdef;
  83.     adr oldOpenWindow, wfargs;
  84.     long waitret;
  85.     bool onecmd, dos2;
  86. } stuffy;
  87.  
  88.  
  89. adr IntuitionBase, DOSBase, IconBase, DiskfontBase;
  90. struct GfxBase *GfxBase;
  91. struct ExecBase *SysBase;
  92.  
  93. struct WBStartup *WBenchMsg;
  94. struct Process *me;
  95. struct Preferences *prufs;
  96.  
  97. #define PREFSIZE (long) ( (str) &prufs->color3 + 2 - (str) prufs)
  98.  
  99. SCLI *fakli = null;
  100. str prompt, setname;
  101.  
  102. ustr command, processname;
  103. BPTR oriout, fakeseglist;
  104.  
  105. bool lace = false, greenify = false, prod = false, frum = false,
  106.     newfont = false, closeori = false, conman = false, behind = false,
  107.     twocolor = false, smartness = false;
  108.  
  109. char argspot = 0;
  110.  
  111.  
  112. str fontname = "topaz.font";        /* no other choices for now */
  113. long fontsize = 11;
  114.  
  115. stuffy *stuff;
  116.  
  117.  
  118. struct NewScreen scrdef = {
  119.     0, 0, 640, 204,    /* Width and Height will be set later */
  120.     2,        /*  4 colors  */
  121.     0, 0,        /*  detail pen = background so no white stripe at top */
  122.     HIRES,        /* inventor of root beer */
  123.     CUSTOMSCREEN,
  124.     null, null,    /* title (won't actually show) filled in later */
  125.     null, null
  126. };
  127.  
  128.  
  129. #ifdef PUBLICITY
  130.  
  131. long screenerror;
  132.  
  133. #endif
  134.  
  135.  
  136. struct NewWindow windef = {
  137.     0, 4, 640, 200,        /* TopEdge and Height will be set later */
  138.     0, 1,
  139.     0,            /* no idcmp */
  140.     ACTIVATE | BACKDROP | BORDERLESS,
  141.     null, null, null,    /* no special gadget or checkmark, no title */
  142.     null,            /* screen pointer; will get set later */
  143.     null,            /* no custom bitmap */
  144.     0, 0, 0, 0,        /* ignored */
  145.     CUSTOMSCREEN
  146. };
  147.  
  148.  
  149. /* these are all in bud.a */
  150. extern void beginning(), ending(), CloseStuff(), RDF_MoveByte();
  151. extern short StuffOffs, CommandOffs, NameOffs, FakeOffs, WedgeOffs;
  152.  
  153. adr WedgeFunc;
  154.  
  155.  
  156. void exit();
  157.  
  158.  
  159. void spew(s) str s;
  160. {
  161.     register long l = strlen(s);
  162.     if (!oriout && !closeori) {
  163.     closeori = true;
  164.     oriout = OOpen("CON:60/40/450/80/ CLImax error: ");
  165.     }
  166.     if (oriout) Write(oriout, s, l);
  167. }
  168.  
  169.  
  170.  
  171. void cheaprintf(format, arg1 /* , ... */ ) str format; int arg1;
  172. {
  173.     char buffer[512];
  174.     RawDoFmt(format, (adr) &arg1, RDF_MoveByte, buffer);
  175.     spew(buffer);
  176. }
  177.  
  178.  
  179.  
  180. void Die()
  181. {
  182.     BPTR *p, *pp;
  183.     UnLoadSeg(fakeseglist);
  184.     if (stuff->ceedee)
  185.     UnLock(stuff->ceedee);
  186.     if (fakli && fakli->cli_CommandDir) {
  187.     p = gbip(fakli->cli_CommandDir);
  188.     while (p) {
  189.         UnLock(p[1]);
  190.         pp = gbip(*p);
  191.         FreeMem(p, 8);
  192.         p = pp;
  193.     }
  194.     }
  195.     CloseStuff(stuff);
  196.     exit(10);
  197. }
  198.  
  199.  
  200.  
  201. void OpenStuff()
  202. {   ushort *wbcolor, tallth;
  203.     static ushort lacecolor[4] = GREENISHNESS,
  204.           unlacecolor[4] = DEFAULTISHNESS;
  205.     long collor;    /* that's how Joan spelled it once */
  206.     struct ViewPort *vp;
  207.     short margin = (lace ? GfxBase->DefaultFont->tf_YSize + 3 : 4);
  208.  
  209.     tallth = (GfxBase->NormalDisplayRows << lace) - margin;
  210.     if (tallth < (200 << lace))
  211.     tallth = 200 << lace;
  212.     else if (tallth > (246 << lace) && tallth < (256 << lace))
  213.     tallth = 256 << lace;
  214.     if (lace)
  215.     scrdef.ViewModes = HIRES | LACE;
  216.     if (stuff->dos2 && !smartness) {
  217.     windef.Flags |= SIMPLE_REFRESH;        /* so text cut w/ mouse works */
  218. #ifdef PUBLICITY
  219.     scrdef.Type = PUBLICSCREEN;
  220. #endif
  221.     }
  222.     if (behind) {
  223.     scrdef.Type |= SCREENBEHIND;
  224.     windef.Flags &= ~ACTIVATE;
  225.     }
  226.     if (twocolor) scrdef.Depth = 1;
  227.     windef.TopEdge = margin;
  228.     windef.Height = prod ? 480 - margin : tallth;
  229.     scrdef.Height = prod ? 480 : tallth + margin;
  230.     scrdef.Width = windef.Width = prod ? 640 : GfxBase->NormalDisplayColumns;
  231.     if (prod) scrdef.LeftEdge = GfxBase->NormalDisplayColumns - 640;
  232.     scrdef.DefaultTitle = processname;
  233.     if (stuff->dos2)
  234.     stuff->scr = OpenScreenTags(&scrdef,
  235. #ifdef PUBLICITY
  236.                     SA_PubName, processname,
  237.                     SA_ErrorCode, &screenerror,
  238. #endif
  239.                     (prod ? SA_DisplayID : TAG_DONE),
  240.                     VGAPRODUCT_KEY, TAG_DONE);
  241.     else
  242.     stuff->scr = OpenScreen(&scrdef);
  243.     if (!stuff->scr) {
  244. #ifdef PUBLICITY
  245.     if (stuff->dos2) switch (screenerror) {
  246.         case OSERR_NOMEM:
  247.         spew("\nCLImax: insufficient memory to open screen.\n");
  248.         break;
  249.         case OSERR_NOCHIPMEM:
  250.         spew("\nCLImax: insufficient chip memory to open screen.\n");
  251.         break;
  252.         case OSERR_PUBNOTUNIQUE:
  253.         spew("\nCLImax: there's already a public screen called \"");
  254.         spew(processname);
  255.         spew("\".\n");
  256.         break;
  257.         default:
  258.         spew("\nCLImax: can't open screen, reason unknown.\n");
  259.     } else
  260. #endif
  261.         spew("\nCLImax: can't open screen.\n");
  262.     Die();
  263.     }
  264.     windef.Screen = stuff->scr;
  265.     stuff->wdef = &windef;
  266.     if (!(stuff->win = OpenWindow(&windef))) {
  267.     spew("\nCLImax: can't open backdrop window.\n");
  268.     Die();
  269.     }
  270.     ShowTitle(stuff->scr, FALSE);
  271.     vp = &stuff->scr->ViewPort;
  272.     prufs = null;
  273.     if (greenify) wbcolor = lacecolor;
  274.     else if (prufs = Alloc(PREFSIZE)) {
  275.     GetPrefs(prufs, PREFSIZE);
  276.     wbcolor = &prufs->color0;
  277.     } else wbcolor = unlacecolor;
  278.     for (collor = 0; collor <= 3; collor++, wbcolor++)
  279.     SetRGB4(vp, collor, (*wbcolor >> 8) & 15L,
  280.             (*wbcolor >> 4) & 15L,
  281.             *wbcolor & 15L);
  282.     if (prufs) FreeMem(prufs, PREFSIZE);
  283. }
  284.  
  285.  
  286.  
  287. BPTR CopyPath(tass) str tass;
  288. {
  289.     struct Process *wb = (adr) FindTask(tass);
  290.     SCLI *wbclap;
  291.     BPTR *wext, *mext, *lastmext, newpath = 0;
  292.     lastmext = &newpath;
  293.     if (!wb) return 0;
  294.     if (!(wbclap = gbip(wb->pr_CLI))) return 0;
  295.     for (wext = gbip(wbclap->cli_CommandDir); wext; wext = gbip(*wext)) {
  296.     if (!(mext = AllocP(2 * sizeof(BPTR))))
  297.         break;
  298.     *lastmext = (long) mext >> 2;
  299.     lastmext = mext;
  300.     mext[1] = DupLock(wext[1]);
  301.     mext[0] = 0;
  302.     }
  303.     return (newpath);
  304. }
  305.  
  306.  
  307.  
  308. void bcpy(dest, src, limit) ubyte *dest, *src; short limit;
  309. {
  310.     register ushort l = *(src++);
  311.     if (l >= limit) l = limit - 1;
  312.     *(dest++) = l;
  313.     while (l > 0) {
  314.     *(dest++) = *(src++);
  315.     l--;
  316.     }
  317. }
  318.  
  319.  
  320.  
  321. void FakeCLI()
  322. {
  323.     if (me->pr_CLI) {
  324.     SCLI *mec = gbip(me->pr_CLI);
  325.     fakli->cli_DefaultStack = mec->cli_DefaultStack;  /* NewCLI does this */
  326.     bcpy(prompt, gbip(mec->cli_Prompt), 64);
  327.     bcpy(setname, gbip(mec->cli_SetName), 88);
  328.     /* I just happen to know that the 1.3 CLI allocates 64 bytes for the
  329.         prompt and 88 bytes for the setname.  On its stack. */
  330.     fakli->cli_CommandDir = CopyPath(null);
  331.     } else {
  332.     register BPTR p;
  333.     fakli->cli_DefaultStack = 1000L;
  334.     if (!(p = CopyPath("Workbench")))
  335.         if (!(p = CopyPath("Initial CLI")))
  336.         if (!(p = CopyPath("AmigaShell")))
  337.             if (!(p = CopyPath("New CLI")))
  338.             p = CopyPath("Background CLI");
  339.     fakli->cli_CommandDir = p;
  340.     /* Why, you ask, am I including code that assumes the CLImax process
  341.        has been launched neither from a CLI nor from Workbench?
  342.        well, I use MyMenu.  and sometimes the path will get set
  343.        elsewhere after workbench is already under way so it doesn't know
  344.        it.  besides, I just had this lying around in FixCLI. */
  345.     }
  346.     fakli->cli_Prompt = (long) prompt >> 2;
  347.     fakli->cli_SetName = (long) setname >> 2;
  348. /*  if (!stuff->ceedee) stuff->ceedee = RLock("SYS:");  */
  349. }
  350.  
  351.  
  352.  
  353. void DooFont()
  354. {
  355.     struct TextAttr f;
  356.     f.ta_Name = (adr) fontname;
  357.     f.ta_YSize = fontsize;
  358.     f.ta_Style = f.ta_Flags = 0;
  359.     stuff->fawnt = OpenFont(&f);
  360.     if (stuff->fawnt && fontsize != stuff->fawnt->tf_YSize) {
  361.     CloseFont(stuff->fawnt);
  362.     stuff->fawnt = null;
  363.     }
  364.     if (!stuff->fawnt)
  365.     if (DiskfontBase = (adr) OpenLibrary("diskfont.library", 0L)) {
  366.         stuff->fawnt = OpenDiskFont(&f);
  367.         CloseLibrary(DiskfontBase);
  368.     }
  369.     if (stuff->fawnt)
  370.     SetFont(stuff->win->RPort, stuff->fawnt);
  371. }
  372.  
  373.  
  374.  
  375. bool wasw = false;
  376.  
  377. bool Scorch(o) char o;
  378. {
  379.     if (o >= '0' && o <= '9' && wasw) {            /* this is way lame */
  380.     stuff->waitret = 10 * stuff->waitret + o - '0';
  381.     return true;
  382.     } else switch (o) {
  383.     case 'g': greenify = true; break;
  384.     case 'i': lace = true; break;
  385.     case 'e': newfont = true; break;
  386.     case 'b': behind = true; break;
  387. #ifdef OLD_SHIT
  388.     case 'm': conman = true; break;
  389. #endif
  390.     case 'p': prod = true; break;
  391.     case '1': twocolor = true; break;
  392.     case 's': smartness = true; break;
  393.     case 'w': stuff->waitret = 0; break;
  394.     default: wasw = false; return false;
  395.     }
  396.     wasw = o == 'w';
  397.     return true;
  398. }
  399.  
  400.  
  401.  
  402. void Wargz()
  403. {
  404.     struct DiskObject *bob;
  405.     str toop;
  406.     register str s;
  407.  
  408.     if (!(IconBase = OpenLibrary("icon.library", 0L))) return;
  409.     CurrentDir(WBenchMsg->sm_ArgList->wa_Lock);
  410.     if (bob = GetDiskObject((ustr) WBenchMsg->sm_ArgList->wa_Name)) {
  411.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "OPTION")) {
  412.         register char c;
  413.         for (c = *toop; c; c = *++toop)
  414.         Scorch(tolower(c));
  415.     }
  416.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "INTERLACE"))
  417.         lace = true;
  418.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "GREEN"))
  419.         greenify = true;
  420.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "TOPAZ11"))
  421.         newfont = true;
  422.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "INACTIVE"))
  423.         behind = true;
  424.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "PRODUCTIVITY"))
  425.         prod = true;
  426.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "TWOCOLOR"))
  427.         twocolor = true;
  428.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "SMARTREFRESH"))
  429.         smartness = true;
  430.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "WAITRETURN"))
  431.         stuff->waitret = atol(toop);
  432.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "ARGINSERT")) {
  433.         while (*toop && *toop <= ' ') toop++;
  434.         if ((argspot = (char) *toop) && WBenchMsg->sm_NumArgs > 1)
  435.         stuff->ceedee = DupLock(WBenchMsg->sm_ArgList[1].wa_Lock);
  436.     }
  437.     if (!argspot && (toop = FindToolType((ustr *) bob->do_ToolTypes, "CD"))) {
  438.         while (*toop && *toop <= ' ') toop++;
  439.         if (stuff->ceedee = RLock(toop)) {
  440.         register int l = strlen(toop);
  441.         if (l >= 88) l = 87;
  442.         *setname = l;
  443.         strncpy(setname + 1, toop, l);
  444.         }
  445.     }
  446.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "FROM")) {
  447.         while (*toop && *toop <= ' ') toop++;
  448.         if (*toop) {
  449.         strcpy(command, "Execute ");
  450.         strcpy(command + 8, toop);
  451.         } else *command = 0;
  452.         frum = true;
  453.     }
  454.     if ((toop = FindToolType((ustr *) bob->do_ToolTypes, "COMMAND"))
  455.             || (toop = FindToolType((ustr *) bob->do_ToolTypes, "DO"))) {
  456.         s = command;
  457.         while (*toop && *toop <= ' ') toop++;
  458.         while (*toop)
  459.         if (*toop == argspot) {
  460.             register str ss;
  461.             if (WBenchMsg->sm_NumArgs > 1)
  462.             ss = WBenchMsg->sm_ArgList[1].wa_Name;
  463.             else ss = "";
  464.             while (*ss) *(s++) = *(ss++);
  465.             toop++;
  466.         } else *(s++) = *(toop++);
  467.         if (!stuff->dos2) strcpy(s, "\nEndCLI >NIL:");
  468.         else *s = 0;
  469.         frum = true;
  470.         stuff->onecmd = -1;
  471.     }
  472.     if (toop = FindToolType((ustr *) bob->do_ToolTypes, "HANDLER")) {
  473.         WFargs.handler = chand;
  474.         strcpy(chand, toop);
  475.         for (s = chand; *s; s++)
  476.         if (*s == ':') *(s--) = 0;
  477.     }
  478.     FreeDiskObject(bob);
  479.     }
  480.     CurrentDir(stuff->ceedee);
  481.     CloseLibrary(IconBase);
  482.     IconBase = null;
  483. }
  484.  
  485.  
  486.  
  487. /* okay, I know perfectly well that this command line parser is really really
  488. lame ... but, the program used to have a really simple syntax that called for a
  489. really simple parser ... and it just sorta grew ... */
  490.  
  491. int word, chair, ac;
  492. ustr *av;
  493.  
  494. ubyte nerg()
  495. {
  496.     if (word > ac) return 0;
  497.     else if (av[word][chair]) return tolower(av[word][chair++]);
  498.     else if (++word <= ac) return tolower(av[word][chair = 0]);
  499.     else return 0;
  500. }
  501.  
  502.  
  503.  
  504. void handle(argc, argv) int argc; str argv[];
  505. {
  506.     ubyte c;
  507.     bool kelp = false, stord = true, opto = false, nul = false;
  508.     char weird[300];
  509.     short wc = 0;
  510.  
  511.     ac = argc; av = (adr) argv; word = 1; chair = 0;
  512.     for (c = nerg(); !nul; c = nerg()) {
  513.     if (stord && c == '-') {
  514.         opto = true;
  515.         c = nerg();
  516.     }
  517.     if (c > ' ' && c != ':') {
  518.         stord = false;
  519.         if (opto) {
  520.         if (!Scorch(c))
  521.             cheaprintf("Unknown option \"-%lc\".\n", (long) c);
  522.         } else weird[wc++] = c;
  523.     } else {
  524.         opto = false;
  525.         stord = true;
  526.         weird[wc] = 0;
  527.         if (wc) {
  528.         wc = 0;
  529.         if (c == ':') {
  530.             strcpy(chand, weird);
  531.             WFargs.handler = &chand[0];
  532.         } else if (weird[0] == '?' || weird[0] == 'h')
  533.             kelp = true;
  534.         else if (!strcmp(weird, "from") || !strcmp(weird, "do")) {
  535.             frum = true;
  536.             stuff->onecmd = - (long) (weird[0] == 'd');
  537.             for (c = nerg(); c && c <= ' '; c = nerg()) ;
  538.             if (!c)
  539.             *command = 0;
  540.             else {
  541.             register ustr cc;
  542.             if (!stuff->onecmd) {
  543.                 cc = command + 8;
  544.                 strcpy(command, "Execute ");
  545.             } else
  546.                 cc = command;
  547.             while (c) {
  548.                 *(cc++) = (ubyte) c;
  549.                 c = nerg();
  550.             }
  551.             if (stuff->onecmd && !stuff->dos2)
  552.                 strcpy(cc, "\nEndCLI >NIL:");
  553.             }
  554.         } else {
  555.             cheaprintf("Unrecognized option: \"%s\".  Usage:  " BOLD
  556.                 "%s ?" NORMAL " or\n" BOLD "%s" NORMAL
  557.                 " { -options } [ handler: ] [ " BOLD "FROM"
  558.                 NORMAL " [ scriptfile ] | " BOLD "DO" NORMAL
  559.                 " command ]\n\n", weird, argv[0], argv[0]);
  560.             Die();
  561.         }
  562.         }
  563.     }
  564.     nul = !c;
  565.     }
  566.     if (kelp) {
  567.     spew(
  568. "\nCLImax by Paul Kienitz -- in the public domain -- usage:\n\n"
  569. "   CLIMAX  { -options }  [ handler: ] [ FROM [ scriptfile ] | DO command ]\n\n"
  570. " -" BOLD "I" NORMAL " = use an interlace screen.       -"
  571. BOLD "E" NORMAL  " = use the Topaz 11 font.\n"
  572. " -" BOLD "P" NORMAL " = use productivity mode.         -"
  573. BOLD "G" NORMAL " = use black-on-green (less flicker).\n"
  574. " -" BOLD "S" NORMAL " = use SMART_REFRESH window.      -"
  575. BOLD "1" NORMAL " = use one bitplane (two colors).\n"
  576. " -" BOLD "B" NORMAL " = open with an inactive window behind other screens.\n"
  577. " -" BOLD "W" NORMAL
  578.     " = wait for Return before exiting after running DO command.  Under 2.0:\n"
  579. " -" BOLD "W" NORMAL "n (e.g. " BOLD "-W10" NORMAL
  580.     ") = wait for Return if DO command fails; n is fail level.\n"
  581. " " BOLD "handler:" NORMAL
  582.     " is a console handler, e.g. NEWCON: or GMC: -- default is CON:.\n"
  583. " " BOLD "FROM [scriptfile]" NORMAL
  584.     " means execute the named file before the first prompt.\n"
  585. "     Must be the last option in the command.  Default is S:Shell-Startup if\n"
  586. "     FROM is not used; use FROM with nothing after it to use no script.\n"
  587. " " BOLD "DO command" NORMAL
  588.     " means run just this CLI command and then exit.  May be\n"
  589. "     continued onto multiple lines with a + at the end of each line.\n"
  590. "Use " BOLD "climax ?" NORMAL " or " BOLD "climax H" NORMAL " to show this message.\n"
  591. "See documentation for Workbench tooltypes equivalent to the above options.\n");
  592.     Die();
  593.     }
  594.     stuff->ceedee = DupLock(me->pr_CurrentDir);
  595. }
  596.  
  597.  
  598.  
  599. void Bud()    /* grow a "bud" which can detach as a child process */
  600. {
  601.     long tize = (long) (((str) &ending - (str) &beginning) + 11) & ~3;
  602.     register str taskspace = AllocP(tize);
  603.     if (!taskspace || !IntuitionBase || !GfxBase) {
  604.     spew("\nGaaah!  Not enough memory for CLImax!\n");
  605.     exit(20);
  606.     }
  607.     CopyMemQuick((str) &beginning, taskspace + 8, tize - 8);
  608.     *((long *) taskspace) = tize;
  609.     ((long *) taskspace)[1] = 0;        /* fakeseglist next bptr */
  610.     fakeseglist = (((long) taskspace) >> 2) + 1;
  611.     taskspace += 8;
  612.     command = (adr) (taskspace + CommandOffs);
  613.     processname = (adr) (taskspace + NameOffs);
  614.     WedgeFunc = taskspace + WedgeOffs;
  615.     if (FindTask(processname))            /* create unique name for */
  616.     processname[6] = '0';            /* task, public screen,   */
  617.     while (FindTask(processname))        /* and screen title       */
  618.     processname[6]++;
  619.     fakli = (adr) (taskspace + FakeOffs);
  620.     prompt = (str) fakli + sizeof(SCLI);
  621.     setname = prompt + 64;
  622.     stuff = (adr) (taskspace + StuffOffs);
  623.     stuff->wandle = stuff->ceedee = 0;
  624.     stuff->scr = (adr) stuff->win = stuff->fawnt = null;
  625.     stuff->ibase = IntuitionBase;
  626.     stuff->gbase = GfxBase;
  627.     stuff->dosbase = DOSBase;
  628.     stuff->onecmd = 0;
  629.     stuff->waitret = -1;
  630. }
  631.  
  632.  
  633.  
  634. void WedgeTheWindowOpen(conspec) str conspec;
  635. {
  636.     struct SignalSemaphore gate, *g;
  637.     char gatename[50];
  638.  
  639.     Forbid();
  640.     if (!(g = FindSemaphore(SEMNAME))) {
  641.     g = &gate;
  642.     gate.ss_Link.ln_Name = &gatename[0];
  643.     strcpy(gatename, SEMNAME);
  644.     gate.ss_Link.ln_Pri = -20;
  645.     /* AddSemaphore */
  646.     InitSemaphore(&gate);
  647.     Enqueue(&SysBase->SemaphoreList, (adr) &gate);
  648.     }
  649.     ObtainSemaphore(g);
  650.     Permit();
  651.  
  652.     /* this is the operation that must not happen in two CLImax processes at the
  653.     same time -- we open the CON spec while the OpenWindow function is
  654.     wedged, so that our console handler process gets back a different window
  655.     from the one it asked for. */
  656.     stuff->oldOpenWindow = (adr) SetFunction(IntuitionBase, -204, WedgeFunc);
  657.     stuff->wandle = OOpen(conspec);
  658.     SetFunction(IntuitionBase, -204, stuff->oldOpenWindow);
  659.  
  660.     if (g == &gate) RemSemaphore(g);
  661.     ReleaseSemaphore(g);
  662.     /* at this point, another CLImax process JUST MIGHT POSSIBLY have obtained
  663.     our semaphore at the moment we released it.  We have to wait for it to
  664.     release, before we deallocate it.  So: */
  665.     if (g == &gate) {
  666.     ObtainSemaphore(g);
  667.     ReleaseSemaphore(g);
  668.     }
  669.     /* Since Obtains are processed in first-in-first-out order, there cannot be
  670.     any obtains waiting after this last one, which was made after gate was
  671.     removed from the public list. */
  672. }
  673.  
  674.  
  675.  
  676. void main(argc, argv) int argc; str *argv;
  677. {
  678.     ubyte boof[150];
  679.     BPTR L, Seg = 1;
  680.     APTR mywptr;
  681.  
  682.     oriout = Output();
  683. #ifndef AZTEC_C
  684.     me = ThisProcess();
  685.     === !do something to get WBenchMsg ===
  686. #endif
  687.     IntuitionBase = (adr) OpenLibrary ("intuition.library", 0L);
  688.     GfxBase = (adr) OpenLibrary ("graphics.library", 0L);
  689.     Bud();
  690.     stuff->dos2 = ((struct Library *) GfxBase)->lib_Version >= 36;
  691.     if (WBenchMsg)
  692.     Wargz();
  693.     else
  694.     handle(argc, argv);
  695.     if (prod) lace = true;
  696.     OpenStuff();
  697.  
  698.     mywptr = me->pr_WindowPtr;
  699.     me->pr_WindowPtr = (APTR) -1L;
  700.     if (!frum)
  701.     if (L = RLock("S:Shell-Startup")) {
  702.         strcpy(command, "Execute S:Shell-Startup");
  703.         UnLock(L);
  704.     } else *command = 0;
  705.     me->pr_WindowPtr = mywptr;
  706.     FakeCLI();
  707.     if (newfont) DooFont();
  708.     WFargs.windowptr = stuff->win;
  709.     stuff->wfargs = &WFargs;
  710.     RawDoFmt("%s:%d/%d/%d/%d/%s/WINDOW 0x%lx", &WFargs, RDF_MoveByte, boof);
  711.     if (stuff->dos2) CacheClearU();
  712.  
  713.     WedgeTheWindowOpen(boof);
  714.     if (stuff->wandle) {
  715.     if (stuff->onecmd)
  716.         fakli->cli_FailLevel = maxint;        /* doesn't work */
  717.     else {
  718.         Write(stuff->wandle, "CLImax by Paul Kienitz maximizes your CLI.\n", 43L);
  719.         stuff->waitret = -1;
  720.     }
  721.     CreateProc(processname, 0L, fakeseglist, 2000L);
  722.     } else {
  723.     cheaprintf("\nCLImax can't open the %s: handler for the window.\n",
  724.             WFargs.handler);
  725.     Die();
  726.     }
  727. }
  728.  
  729.  
  730.  
  731. /* reduce size by a few K: */
  732.  
  733. #ifdef AZTEC_C
  734.  
  735. char arg[256], prame[256];
  736. str argp[3];
  737.  
  738.  
  739. void _main(alen, aptr) long alen; str aptr;  /* simplified startup code */
  740. {
  741.     int al = alen;
  742.     ustr poik;
  743.  
  744.     me = ThisProcess();
  745.     poik = bip(char, bip(struct CommandLineInterface,
  746.                   me->pr_CLI)->cli_CommandName);
  747.     if (me->pr_CLI) {
  748.     strncpy(prame, (str) poik + 1, (size_t) *poik);
  749.     prame[*poik] = 0;
  750.     strupr(prame);
  751.     if (al > 255) al = 255;
  752.     argp[0] = prame;        /* do by hand so purify.a works **/
  753.     argp[1] = arg;
  754.     argp[2] = null;
  755.     strncpy(arg, aptr, al);
  756.     arg[al - 1] = 0;
  757.     WBenchMsg = null;
  758.     } else {
  759.     WaitPort(&me->pr_MsgPort);
  760.     WBenchMsg = (adr) GetMsg(&me->pr_MsgPort);
  761.     }
  762.     main(1, argp);    /* pack all args into argv[1] */
  763.     exit(0);
  764. }
  765.  
  766.  
  767.  
  768. void exit(code) int code;
  769. {
  770.     char c;
  771.     if (oriout && closeori) {
  772.     spew("\n  -- press return:  ");
  773.     Read(oriout, &c, 1L);
  774.     Close(oriout);
  775.     }
  776.     if (WBenchMsg) {
  777.     Forbid();
  778.     ReplyMsg((struct Message *) WBenchMsg);
  779.     }
  780.     Exit((long) code);
  781. }
  782.  
  783. #endif
  784.